package com.codeyang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codeyang.dao.ProdEsDao;
import com.codeyang.domain.Prod;
import com.codeyang.domain.ProdComm;
import com.codeyang.domain.User;
import com.codeyang.dto.ProdCommDto;
import com.codeyang.es.ProdEs;
import com.codeyang.feign.ProdCommUserFeign;
import com.codeyang.mapper.ProdCommMapper;
import com.codeyang.mapper.ProdMapper;
import com.codeyang.service.ProdCommService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 描述: TO-删除标志-DO
 *
 * @author CodeYang_Site
 * @version 2021/5/24 22:34
 */
@Service
public class ProdCommServiceImpl extends ServiceImpl<ProdCommMapper, ProdComm> implements ProdCommService {

    @Autowired
    private ProdMapper prodMapper;

    @Autowired
    private ProdCommMapper prodCommMapper;


    @Autowired
    private ProdEsDao prodEsDao;

    @Autowired
    private ProdCommUserFeign prodCommUserFeign;

    /**
     * 根据 prodComm 条件|无条件分页查询 商品评论表
     * 步骤: 三步走 1查 yes 2no 查 存 3.组装
     * 现在还没有启用redis来存数据,直接干
     * step:
     * 1   有商品名 直接全查询 组装商品评论Page
     * 1.1 先查询商品表得到 商品ids集合
     * 1.2 查询商品评论表 得到 List<ProdComm>
     * 1.3  组装返回Page对象 循环 List<ProdComm> 找到对应的商品对象 设置商品名字
     * 2. 没有商品名
     * 2.1直接查询 商品评论表 拿到商品ids
     * 2.2查询商品表 List<Prod>
     * 2.3 循环组装数据
     * </Prod>
     *
     * @param page
     * @param prodComm
     * @return Page<ProdComm>
     */
    @Override
    public Page<ProdComm> findPageCommPage(Page<ProdComm> page, ProdComm prodComm) {
        //1.拿到 ProdName
        String prodName = prodComm.getProdName();
        List<Long> prodIds = null;
        List<Prod> prodList = null;
        //2.check name
        if (StringUtils.hasText(prodName)) {
            //yes 根据商品名 查询商品表 得到商品对象结合
            prodList = prodMapper.selectList(new LambdaQueryWrapper<Prod>().like(Prod::getProdName, prodName));

            if (CollectionUtils.isEmpty(prodList)) {
                //如果查询出来的商品为空也是直接返回
                page.setRecords(Collections.emptyList());
                page.setTotal(0L);
                return page;
            }
            //不为空拿到商品ids的集合
            prodIds = prodList.stream()
                    .map(Prod::getProdId)
                    .collect(Collectors.toList());
        }

        // 不管有没有用户名都是要查询用户评论表的
        // 分页+可能存在的用户条件查询 用户评论表  记录
        Page<ProdComm> prodCommPage = prodCommMapper.selectPage(page, new LambdaQueryWrapper<ProdComm>()
                .in(!CollectionUtils.isEmpty(prodIds), ProdComm::getProdId, prodIds)
                .orderByDesc(ProdComm::getRecTime)
        );

        // 拿到份分页数据
        List<ProdComm> prodCommList = prodCommPage.getRecords();
        //3组装数据
        if (!CollectionUtils.isEmpty(prodCommList)) {
            // 拿到查询记录中的 商品ids集合
            List<Long> ids = prodCommList.stream().map(ProdComm::getProdId).collect(Collectors.toList());
            // 在使用这个ids 精确查询DB 得到对应的商品表记录
            List<Prod> prods = prodMapper.selectList(new LambdaQueryWrapper<Prod>().in(Prod::getProdId, ids));

            // 循环组装 商品评论数据 将商品名组装进来
            prodCommList.forEach(prodCommItem -> {
                //过滤拿到一条商品对象
                Prod prodEntrty = prods.stream()
                        //直接循环比对 分页数据中商品id相同的记录
                        .filter(prod -> prod.getProdId().equals(prodCommItem.getProdId()))
                        .collect(Collectors.toList())
                        .get(0);
                //设置商品名称 为每个商品评论记录
                prodCommItem.setProdName(prodEntrty.getProdName());
            });

        }
        return prodCommPage;
    }


    /**
     * 根据商品id查询商品评论总览信息
     * 根据商品id查询商品评论总览
     * 注意:
     * 不建议在java中一下查出20+的数据量
     * 对数据库连接和性能都不好
     * 可以采用小的查询 多查几次
     * 分时操作了,有时间间隔
     * 这里如果数据小 分几次SQL 涉及关键数据,可能会发生数据 賍读
     *
     * @param prodId
     * @return
     */
    @Override
    public ProdCommDto findProdCommDtoByProdId(Long prodId) {
        //1.好评率和好评数es中已经有了,直接拿

        ProdEs prodEs = prodEsDao.findById(prodId).get();
        //好评率
        BigDecimal positiveRating = prodEs.getPositiveRating();
        //好评数
        Long praiseNumber = prodEs.getPraiseNumber();
        // 分成几个短SQl去查询 评论质量
        // 总评数  中评 差评 带图
        Integer allProdComm = prodCommMapper.selectCount(new LambdaQueryWrapper<ProdComm>()
                .eq(ProdComm::getProdId, prodId)
                .eq(ProdComm::getStatus, 1)
        );

        Integer secondComm = prodCommMapper.selectCount(new LambdaQueryWrapper<ProdComm>()
                .eq(ProdComm::getProdId, prodId)
                .eq(ProdComm::getStatus, 1)
                .eq(ProdComm::getEvaluate, 1)
        );

        Integer badComm = prodCommMapper.selectCount(new LambdaQueryWrapper<ProdComm>()
                .eq(ProdComm::getProdId, prodId)
                .eq(ProdComm::getStatus, 1)
                .eq(ProdComm::getEvaluate, 2)
        );

        Integer picComm = prodCommMapper.selectCount(new LambdaQueryWrapper<ProdComm>()
                .eq(ProdComm::getProdId, prodId)
                .eq(ProdComm::getStatus, 1)
                .eq(ProdComm::getEvaluate, 3)
        );

        ProdCommDto prodCommDto = ProdCommDto.builder()
                .praiseNumber(praiseNumber)
                .positiveRating(positiveRating)
                .secondaryNumber(secondComm.longValue())
                .negativeNumber(badComm.longValue())
                .picNumber(picComm.longValue())
                .number(allProdComm.longValue())
                .build();
        // 特殊字符脱敏处理,还没有做过
        return prodCommDto;
    }

    /**
     * 根据用户id分页查询用户评论信息和用户信息
     *
     * @param prodId
     * @param size
     * @param current
     * @param evaluate
     * @return
     */
    @Override
    public Page<ProdComm> prodCommPageByProd(Long prodId, Integer size, Integer current, Integer evaluate) {
        Page<ProdComm> page = new Page<>(current, size);
        //1.先分页查询评论
        Page<ProdComm> prodCommPage = prodCommMapper.selectPage(page,
                new LambdaQueryWrapper<ProdComm>()
                        .eq(ProdComm::getProdId, prodId)
                        //-1是全查询就没有必要加这个条件了
                        .eq(null != evaluate && !evaluate.equals(-1), ProdComm::getEvaluate, evaluate)
                        .orderByDesc(ProdComm::getScore, ProdComm::getRecTime)
        );
        //拿到 商品评论信息
        // 但是一个商品下面可能有好几个用户的评论
        List<ProdComm> pageRecords = prodCommPage.getRecords();
        //商品评论表里有用户的id
        //拿到用户的id

        Set<String> userIds = pageRecords.stream().map(ProdComm::getUserId).collect(Collectors.toSet());

        // 调用远程服务,拿到用户的昵称和用户pic
        List<User> users = prodCommUserFeign.getUsersByIds(userIds);

        if (!CollectionUtils.isEmpty(users)) {
            //处理头像和昵称
            pageRecords.forEach(prodComm -> {
                List<User> userList = users
                        .stream()
                        .filter(user -> user.getUserId().equals(prodComm.getUserId()))
                        .collect(Collectors.toList());
                User user = users.get(0);
                prodComm.setPic(user.getPic());
                prodComm.setNickName(user.getNickName());
            });

        }
        return prodCommPage;
    }
}
